<?php

use AlibabaCloud\SDK\Facebody\V20191230\Facebody;
use AlibabaCloud\SDK\Facebody\V20191230\Models\GetFaceEntityRequest;
use AlibabaCloud\SDK\Facebody\V20191230\Models\AddFaceEntityRequest;
use AlibabaCloud\SDK\Facebody\V20191230\Models\AddFaceRequest;
use AlibabaCloud\SDK\Facebody\V20191230\Models\DeleteFaceRequest;
use AlibabaCloud\SDK\Facebody\V20191230\Models\SearchFaceRequest;
use AlibabaCloud\SDK\Facebody\V20191230\Models\CreateFaceDbRequest;
use AlibabaCloud\SDK\Sts\V20150401\Models\AssumeRoleRequest;
use AlibabaCloud\SDK\Sts\V20150401\Sts;
use Darabonba\OpenApi\Models\Config;
use think\facade\Config as ThinkConfig;
use think\facade\Cache;

class AliFaceBodyService
{
    private static $dbName = 'banpai';

    /**
     * 使用AK&SK初始化账号Client
     */
    public static function createClient()
    {
        $thinkConfig = ThinkConfig::get();
        $config      = new Config(
            [
                'accessKeyId'     => $thinkConfig['alists']['id'],
                'accessKeySecret' => $thinkConfig['alists']['secret'],
                'endpoint'        => 'facebody.cn-shanghai.aliyuncs.com'
            ]
        );

        return new Facebody($config);
    }

    public static function saveFace($entityId, $img, $extraData = '')
    {
        $entityId = $extraData . '_' . $entityId;
        $faces    = self::getFaceEntity($entityId);
        if ($faces) {
            foreach ($faces as $face) {
                self::deleteFace($face->faceId);
            }
        } else {
            self::addFaceEntity($entityId);
        }
        self::addFace($entityId, $img, $extraData);
    }

    public static function searchFace($img): string
    {
        $client   = self::createClient();
        $request  = new SearchFaceRequest(['dbName' => self::$dbName, 'imageUrl' => $img, 'limit' => 1]);
        $response = $client->searchFace($request);
        if (empty($response->body->data->matchList)) {
            throw new \Exception('识别失败!');
        }
        if (empty($response->body->data->matchList[0]->faceItems)) {
            throw new \Exception('识别失败!');
        }

        return $response->body->data->matchList[0]->faceItems[0]->entityId;
    }

    public static function getFaceEntity($entityId): array
    {
        $client   = self::createClient();
        $request  = new GetFaceEntityRequest(['dbName' => self::$dbName, 'entityId' => $entityId]);
        $response = $client->getFaceEntity($request);
        if (!$response->body->data) {
            return [];
        }

        return $response->body->data->faces;
    }

    public static function addFaceEntity($entityId, $labels = '')
    {
        $client  = self::createClient();
        $request = new AddFaceEntityRequest(['dbName' => self::$dbName, 'entityId' => $entityId, 'labels' => $labels]);
        $client->addFaceEntity($request);
    }

    public static function addFace($entityId, $img, $extraData = '')
    {
        $client = self::createClient();
        $request = new AddFaceRequest(
            ['dbName' => self::$dbName, 'entityId' => $entityId, 'imageUrl' => $img, 'extraData' => $extraData]
        );
        $client->addFace($request);
    }

    public static function deleteFace($faceId)
    {
        $client  = self::createClient();
        $request = new DeleteFaceRequest(['dbName' => self::$dbName, 'faceId' => $faceId]);
        $client->deleteFace($request);
    }

    public static function createFaceDb()
    {
        $client   = self::createClient();
        $request  = new CreateFaceDbRequest(['name' => self::$dbName]);
        $response = $client->createFaceDb($request);
    }

    public static function getStsToken()
    {
        return Cache::remember(
            'ali-sts',
            function () {
                $thinkConfig = ThinkConfig::get();
                $config      = new Config(
                    [
                        'accessKeyId'     => $thinkConfig['alists']['id'],
                        'accessKeySecret' => $thinkConfig['alists']['secret'],
                        'endpoint'        => $thinkConfig['alists']['endpoint']
                    ]
                );
                $client      = new Sts($config);
                $request     = new AssumeRoleRequest(
                    ['roleArn' => $thinkConfig['alists']['arn'], 'roleSessionName' => 'banpai']
                );
                $response    = $client->assumeRole($request);

                return $response->body->credentials;
            },
            3000
        );
    }
}